use super::{ConstantInfo, ClassReader};

// CONSTANT_Utf8_info {
// u1 tag;   // 值为1
// u2 length; // 长度
// u1 bytes[length]; // 字符串bytes
// }
pub struct ConstantUtf8Info {
    str: String
}

impl ConstantInfo for ConstantUtf8Info {
    fn read_info(&mut self, reader: &mut ClassReader){
        let lenght = reader.read_u16() as usize;
        let bytes = reader.read_bytes(lenght);
        self.str = decode_mutf8(bytes);
    }
}

impl ConstantUtf8Info {
    pub fn new() -> ConstantUtf8Info {
        ConstantUtf8Info { str: String::new() }
    }

    pub fn str(&self) -> String {
        self.str.clone()
    }
}


// 在 Rust 中，位运算符和左移右移的优先级是按照以下顺序排列的：
// 左移运算符 <<：将二进制数的所有位向左移动指定的位数，并在右侧用零填充空出的位。
// 右移运算符 >>：将二进制数的所有位向右移动指定的位数。对于有符号整数，空出的位将用符号位填充；对于无符号整数，空出的位将用零填充。
// 按位与运算符 &：将两个二进制数的对应位进行按位与运算，得到一个新的二进制数。
// 按位异或运算符 ^：将两个二进制数的对应位进行按位异或运算，得到一个新的二进制数。
// 按位或运算符 |：将两个二进制数的对应位进行按位或运算，得到一个新的二进制数。

#[allow(warnings)]
// 将Vec<u8> 转为 MUTF8字符串
fn decode_mutf8(bytearr: Vec<u8>) -> String {
    let utflen = bytearr.len();
    let mut chararr = vec![];
    let (mut c, mut char2, mut char3) = (0u16, 0u16, 0u16);
    let mut count = 0usize;
    // 只处理ascii提高速度
    while count < utflen {
        c = bytearr[count].into();
        if c > 127 {
            break;
        }
        count += 1;
        chararr.push(c);
    }

    while count < utflen {
        c = bytearr[count].into();
        match c >> 4 {
            0..=7 => { 
                // 0xxxxxxx
                count += 1;
                chararr.push(c);
            },
            12 | 13 => {
                // 110xxxxx 10xxxxxx
                count += 2;
                if count > utflen {
                    panic!("malformed input: partial character at end")
                }
                char2 = bytearr[count - 1].into();
                if char2 & 0xc0 != 0x80 {
                    panic!("malformed input around byte {}", count)
                }
                chararr.push((c & 0x1F) << 6 | char2 & 0x3F);
            },
            14 => {
                // 1110xxxx 10xxxxxx 10xxxxxx
                count += 3;
                if count > utflen {
                    panic!("malformed input: partial character at end")
                }
                char2 = bytearr[count - 2].into();
                char3 = bytearr[count - 1].into();
                if char2 & 0xc0 != 0x80 || char3 & 0xC0 != 0x80 {
                    panic!("malformed input around byte {}", count)
                }
                chararr.push((c & 0x0F) << 12 | (char2 & 0x3F) << 6 | char3 & 0x3F);
            },
            _ => panic!("malformed input around byte {}", count)
        }
    }
    let runes = String::from_utf16(&chararr[..]);
    runes.unwrap()
}



#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn mutf8_test() {
        // C0 80 C0 80
        let vec = vec![0xc0, 0x80,0xc0, 0x80, 0x01, 0xc0, 0x80, 0x01, 0x01];
        let s = decode_mutf8(vec).encode_utf16().collect::<Vec<u16>>();
        assert_eq!(s, vec![0, 0, 1, 0, 1, 1]);
    }
}